Skip to content

9.26 实体数据监听器

📝 模块更新日志 问题修复*

+ 修复 `EFCore` 实体监听器 `IEntityChangedListener` 问题 4\.8\.1\.7 ⏱️2022\.11\.26 [\#I61CTI](https://gitee.com/dotnetchina/Furion/issues/I61CTI)

9.26.1 实体数据监听器

在最新的 Furion1.1.6+ 版本中,新增了 IEntityChangedListener 实体数据监听接口,可以监听 EFCore 任何实体表 增删改 操作。

9.26.2 有何作用

  • 类似数据库 触发器 功能,可实现 增删改 监听
  • 可以实现特殊操作,比如刷新缓存,记录日志等

9.26.3 如何使用

Furion 框架中,默认不启用实体数据监听器,如想启用,只需要在 数据库上下文 构造函数中启用即可:

9.26.3.1 启用数据监听

using Furion.DatabaseAccessor;  
using Microsoft.EntityFrameworkCore;  

namespace Furion.EntityFramework.Core  
{  
    [AppDbContext("Sqlite3ConnectionString")]  
    public class DefaultDbContext : AppDbContext<DefaultDbContext>  
    {  
        public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)  
        {  
            EnabledEntityChangedListener = true;  
        }  
    }  
}  

9.26.3.2 监听特定实体数据

特别注意如果实体没有直接或间接继承 Entity 或者 EntityBase,那么需要在实体中添加 __State__ 非公开属性,如:

internal EntityState __State__ { get; set; }  

using Furion.DatabaseAccessor;  
using Microsoft.EntityFrameworkCore;  
using Microsoft.Extensions.Caching.Memory;  
using System;  
using System.Collections.Generic;  

namespace Furion.Core  
{  
    public class Post : Entity, IEntityChangedListener<Post>  
    {  
        /// <summary>  
        /// 构造函数  
        /// </summary>  
        public Post()  
        {  
            CreatedTime = DateTimeOffset.UtcNow;  
            IsDeleted = false;  
        }  

        /// <summary>  
        /// 名称  
        /// </summary>  
        public string Name { get; set; }  

        /// <summary>  
        /// Person 集合  
        /// </summary>  
        public ICollection<Person> Persons { get; set; }  

        /// <summary>  
        /// 实体更改后触发  
        /// </summary>  
        /// <param name="entity">新数据</param>  
        /// <param name="oldEntity">旧数据</param>  
        /// <param name="dbContext">数据库上下文</param>  
        /// <param name="dbContextLocator">数据库上下文定位器</param>  
        /// <param name="state">实体状态</param>  
        public void OnChanged(Post entity, Post oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state)  
        {  
            // 刷新缓存  
            App.GetService<IMemoryCache>().Set("Key", "Value");  
        }  
    }  
}  

9.26.4 IEntityChangedListener 定义

/// <summary>  
/// 实体数据改变监听依赖接口  
/// </summary>  
/// <typeparam name="TEntity"></typeparam>  
public interface IEntityChangedListener<TEntity>  
    where TEntity : class, IPrivateEntity, new()  
{  
    /// <summary>  
    /// 监听数据改变之前(仅支持EFCore操作)  
    /// </summary>  
    /// <param name="entity"></param>  
    /// <param name="dbContext"></param>  
    /// <param name="dbContextLocator"></param>  
    /// <param name="state"></param>  
    void OnChanging(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }  

    /// <summary>  
    /// 监听数据改变之后(仅支持EFCore操作)  
    /// </summary>  
    /// <param name="newEntity">新值</param>  
    /// <param name="oldEntity">旧值</param>  
    /// <param name="dbContext"></param>  
    /// <param name="dbContextLocator"></param>  
    /// <param name="state"></param>  
    void OnChanged(TEntity newEntity, TEntity oldEntity, DbContext dbContext, Type dbContextLocator, EntityState state);  

    /// <summary>  
    /// 监听数据改变失败(仅支持EFCore操作)  
    /// </summary>  
    /// <param name="entity"></param>  
    /// <param name="dbContext"></param>  
    /// <param name="dbContextLocator"></param>  
    /// <param name="state"></param>  
    void OnChangeFailed(TEntity entity, DbContext dbContext, Type dbContextLocator, EntityState state) { }  
}  

9.26.5 [SuppressChangedListener] 跳过监听

默认情况下,Furion 框架会对所有新增、更新、编辑的实体进行监听,有些时候我们无需监听特定实体,只需要在实体上贴 [SuppressChangedListener] 特性即可。

9.26.6 反馈与建议

与我们交流给 Furion 提 Issue